package com.lzp.leetcode.array;

import java.util.Arrays;

/**
 * 数组拆分1
 * 给定长度为 2n 的数组, 你的任务是将这些数分成 n 对, 例如 (a1, b1), (a2, b2), ..., (an, bn) ，使得从1 到 n 的 min(ai, bi) 总和最大。
 *
 * @author lzp
 * @date 2020/04/19
 */
public class LC561 {

    /**
     * 思路1：先排序，然后取索引位置为偶数对应值的和
     * O(nlog(n))
     * O(1)
     *
     * @param nums
     * @return
     */
    public int arrayPairSum2(int[] nums) {
        // 快排/归并/插入 【nlogn】
        Arrays.sort(nums);
        int result = 0;
        // 遍历偶数索引位置的值加和 【n】
        for (int i = 0; i < nums.length; i += 2) {
            result += nums[i];
        }
        return result;
    }

    /**
     * 暴力求解法：找出给定数组元素的所有可能排列
     */
    int max_sum = Integer.MIN_VALUE;

    public int arrayPairSum(int[] nums) {
        permute(nums, 0);
        return max_sum;
    }

    public void permute(int[] nums, int l) {
        // 递归终止条件
        if (l == nums.length - 1) {
            int sum = 0;
            // 对当前排列求和，保存最大值
            for (int i = 0; i < nums.length; i += 2) {
                sum += Math.min(nums[i], nums[i + 1]);
            }
            max_sum = Math.max(max_sum, sum);
        }
        for (int i = l; i < nums.length; i++) {
            // 调换位置 1,[3,4,2]
            swap(nums, i, l);
            // 对子集进行操作[1,4,3,2]==> 1,[4,3,2]
            permute(nums, l + 1);
            // 调换回去 1,[4,3,2]
            swap(nums, i, l);
        }
    }

    public void swap(int[] nums, int x, int y) {
        int temp = nums[x];
        nums[x] = nums[y];
        nums[y] = temp;
    }

    public static void main(String[] args) {
        int[] nums = new int[]{1, 4, 3, 2};
        System.out.println(new LC561().arrayPairSum(nums));
    }
}
